package com.yxsk.relay.job.admin.web.controller;

import com.yxsk.relay.job.admin.core.log.EndpointLogService;
import com.yxsk.relay.job.admin.data.entity.*;
import com.yxsk.relay.job.admin.data.service.*;
import com.yxsk.relay.job.admin.web.common.data.PageSort;
import com.yxsk.relay.job.admin.web.common.exception.RelayAdminWebRuntimeException;
import com.yxsk.relay.job.component.common.constant.NetProtocol;
import com.yxsk.relay.job.component.common.exception.RelayJobRuntimeException;
import com.yxsk.relay.job.component.common.exception.remote.RemoteCallException;
import com.yxsk.relay.job.component.common.vo.Endpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author 11376
 * @CreaTime 2019/6/27 19:59
 * @Description
 */
@Controller
@RequestMapping("/admin/quartz/job/trigger")
public class AdminTriggerLogController extends BaseController<JobTriggerLog, JobTriggerLogService> {

    @Autowired
    private JobAppsService appsService;
    @Autowired
    private JobDetailService jobDetailService;
    @Autowired
    private JobExecuteLogService executeLogService;
    @Autowired
    private JobPartitionLogService partitionLogService;
    @Autowired
    private JobCollectLogService collectLogService;
    @Autowired
    private EndpointLogService logService;

    @GetMapping("")
    public String list(Model model,
                       @RequestParam(value = "appId", required = false) String appId,
                       @RequestParam(value = "jobId", required = false) String jobId,
                       @RequestParam(value = "startTime", required = false) String startTime,
                       @RequestParam(value = "endTime", required = false) String endTime) {
        // 查询应用
        model.addAttribute("apps", this.appsService.findAllNormalEntities());
        // 查询任务
        model.addAttribute("jobs", this.jobDetailService.findAllNormalEntities());

        // 创建分页对象
        PageRequest page = PageSort.nativePageRequest(Sort.Direction.DESC);
        // 查询执行日志
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Page<Map> result = null;
        try {
            result = this.service.findPageByCondition(appId, jobId, StringUtils.hasLength(startTime) ? dateFormat.parse(startTime) : null, StringUtils.hasLength(endTime) ? dateFormat.parse(endTime) : null, page);
        } catch (ParseException e) {
            throw new RelayAdminWebRuntimeException(e);
        }

        List<Map> content = result.getContent();

        if (!CollectionUtils.isEmpty(content)) {
            List<Map<String, Object>> dataList = new ArrayList<>(content.size() * 4 / 3);
            content.stream().forEach(map -> {
                Map<String, Object> copyMap = new HashMap<>(map.size() * 2);
                copyMap.putAll(map);
                String triggerClassName = map.get("TRIGGER_CLASS_NAME").toString();
                copyMap.put("simpleTriggerName", JobDetails.TriggerClassesEnum.getTriggerByClassName(triggerClassName).getTriggerName());
                dataList.add(copyMap);
            });
            model.addAttribute("list", dataList);
        } else {
            model.addAttribute("list", content);
        }

        model.addAttribute("page", result);
        return getBasicDir() + "/index";
    }

    @GetMapping("/info/{id}")
    public String info(@PathVariable("id") String id, Model model) {
        JobTriggerLog triggerLog = this.service.findById(id);
        triggerLog.setJobId(this.jobDetailService.findById(triggerLog.getJobId()).getJobName());
        model.addAttribute("entity", triggerLog);
        return getBasicDir() + "/infoDetail";
    }

    @GetMapping("/execute/{id}")
    public String executeList(@PathVariable("id") String id, Model model) {
        JobTriggerLog triggerLog = this.service.findById(id);
        model.addAttribute("entity", triggerLog);
        // 查询执行日志
        List<JobExecuteLog> list = this.executeLogService.findByTriggerId(id);
        model.addAttribute("list", list);
        return getBasicDir() + "/executeLog";
    }

    @GetMapping("/partitionLogList/{triggerId}")
    public String partitionLogList(@PathVariable("triggerId") String triggerId, Model model) {
        // 查询触发信息
        JobTriggerLog triggerLog = this.service.findById(triggerId);
        model.addAttribute("entity", triggerLog);

        // 查询任务分片日志列表
        List<JobPartitionLog> partitionLogs = this.partitionLogService.findByTriggerLog(triggerId);
        model.addAttribute("list", partitionLogs);
        return getBasicDir() + "/partitionLog";
    }

    @GetMapping("/partitionLogDetails/{partitionId}")
    public String partitionLogDetails(@PathVariable("partitionId") String partitionId, Model model) {
        // 查询分片详情
        JobPartitionLog partitionLog = this.partitionLogService.findById(partitionId);
        model.addAttribute("entity", partitionLog);

        if (partitionLog == null) {
            throw new RelayJobRuntimeException("Partition information is null");
        }
        // 查询日志
        Endpoint endpoint = new Endpoint();
        endpoint.setHost(partitionLog.getEndpointIp());
        endpoint.setPort(partitionLog.getEndpointPort());
        endpoint.setAuthToken(partitionLog.getAuthToken());
        endpoint.setProtocol(NetProtocol.getProtocol(partitionLog.getNetProtocol()));
        try {
            List<String> logs = logService.loadLog(endpoint, partitionLog.getId(), null, null);
            model.addAttribute("logs", logs);
        } catch (RemoteCallException e) {
            throw new RelayJobRuntimeException(e);
        }

        return getBasicDir() + "/partitionLogDetail";
    }

    @GetMapping("/collectLogList/{triggerId}")
    public String collectLogList(@PathVariable("triggerId") String triggerId, Model model) {
        // 查询触发信息
        JobTriggerLog triggerLog = this.service.findById(triggerId);
        model.addAttribute("entity", triggerLog);

        // 查询任务分片日志列表
        List<JobCollectLog> collectLogs = this.collectLogService.findByTriggerLog(triggerId);
        model.addAttribute("list", collectLogs);
        return getBasicDir() + "/collectLog";
    }

    @GetMapping("/collectLogDetails/{collectId}")
    public String collectLogDetails(@PathVariable("collectId") String collectId, Model model) {
        // 查询分片详情
        JobCollectLog collectLog = this.collectLogService.findById(collectId);
        model.addAttribute("entity", collectLog);

        if (collectLog == null) {
            throw new RelayJobRuntimeException("Collect information is null");
        }
        // 查询日志
        Endpoint endpoint = new Endpoint();
        endpoint.setHost(collectLog.getEndpointIp());
        endpoint.setPort(collectLog.getEndpointPort());
        endpoint.setAuthToken(collectLog.getAuthToken());
        endpoint.setProtocol(NetProtocol.getProtocol(collectLog.getNetProtocol()));
        try {
            List<String> logs = logService.loadLog(endpoint, collectLog.getId(), null, null);
            model.addAttribute("logs", logs);
        } catch (RemoteCallException e) {
            throw new RelayJobRuntimeException(e);
        }

        return getBasicDir() + "/collectLogDetail";
    }

    @Override
    protected String getBasicDir() {
        return "/system/job/trigger";
    }

}
